package service

import (
	"context"
	"duoke/internal/dao"
	"duoke/internal/model/entity"
	"duoke/model"
	"duoke/tables"
	utils "duoke/utils/common"
	"duoke/utils/gconv"
	"duoke/utils/gjson"
	"duoke/utils/orm"
	"duoke/utils/redislib"
	"encoding/json"
	"errors"
	"fmt"
	"github.com/gin-gonic/gin"
	"time"
)

var Shortvideo = new(shortvideoService)

type shortvideoService struct{}

// 视频采集url
func (s *shortvideoService) GatherUrl(c *gin.Context, url string) error {
	return nil
}

// 获取详情
func (s *shortvideoService) Info(Id int, field string) (*tables.Shortvideo, error) {
	user := new(tables.Shortvideo)
	has, err := orm.Db.Where("id=?", Id).Cols(field).Get(user)
	if err != nil {
		return nil, err
	}
	if !has {
		return nil, errors.New("短视频不存在")
	}
	key := []byte("Q!fqhthlsFuazZ(gvlWTY(h(n_x*2i4+")
	iv := []byte("Js8K1kDYC^K^FuWZ")
	var m []model.VideoRsp
	err = json.Unmarshal([]byte(user.Video), &m)
	for k, item := range m {
		if item.Type == "video" {
			m[k].Url, _ = utils.Common.AESEncrypt([]byte(item.Url), key, iv)
		}
	}
	marshal, err := json.Marshal(&m)
	user.Video = string(marshal)
	return user, nil
}

func (s *shortvideoService) Watch(c *gin.Context, req *model.VideoClick) error {
	userR, _ := Request.User(c)
	var short tables.Shortvideo
	get, err := orm.Db.Where("id=?", req.Id).Get(&short)
	if err != nil {
		return err
	}
	if !get {
		return errors.New("该短视频不存在")
	}
	var shareUser entity.ShareUser
	_, _ = orm.Db.Where("from_id=? and user_id=? and share_type=?",
		req.Id, userR.Id, req.ShortType).Get(&shareUser)
	state := 1 //用于判断用户是否取消的按钮
	if req.ShortType == 1 {
		if shareUser.Id > 0 && shareUser.State == 1 {
			state = 0
		}
	}
	user := entity.ShareUser{
		FromId:    req.Id,
		FromUser:  short.UserId,
		UserId:    userR.Id,
		ShareType: req.ShortType, // 1点赞 2转发 3 观看
		State:     state,
		Number:    1,
		Acid:      userR.Acid,
	}
	if shareUser.Id > 0 {
		orm.Db.Where("id=?", shareUser.Id).Omit("id").AllCols().Update(&user)
	} else {
		orm.Db.Insert(&user)
	}
	if err != nil {
		return err
	}
	// 转发可以多次
	switch req.ShortType {
	case 1: // 点赞
		if shareUser.Id > 0 && shareUser.State == 1 {
			// 如果存在 再次点击则取消点赞
			short.Dz -= 1
			_, err = orm.Db.Table("shortvideo").Where("id=?", req.Id).
				Omit("id").AllCols().Update(&short)
		} else {
			short.Dz += 1
			_, err = orm.Db.Table("shortvideo").Where("id=?", req.Id).
				Omit("id").Update(&short)
		}
	case 2: //转发
		if shareUser.Id == 0 && state == 1 {
			short.Zf += 1
			_, err = orm.Db.Table("shortvideo").Where("id=?", req.Id).Update(&short)
		}
	}
	//redis 消息队列异步生成小程序二维码
	return nil
}

// Statistics 这里写视频分销逻辑
func (s *shortvideoService) Statistics(c *gin.Context, req *model.ShortVideWs) error {
	user, err := Request.User(c)
	if err != nil {
		return err
	}
	str := "short_video_statistics_" + gconv.String(user.Id)
	redisGet := redislib.Redis.Get(context.Background(), str)
	// 获取以秒为单位的时间戳
	timestampSec := time.Now().Unix()
	var sumTime int64
	var state, points, id int
	if redisGet.Val() == "" {
		redislib.Redis.Set(context.Background(), str, timestampSec, 30*time.Minute) // 存30分钟
		return errors.New("还未到奖励时间")
	} else {
		sumTime = timestampSec - gconv.Int64(redisGet.Val())
		if sumTime >= 30 && sumTime < 60 {
			state = 1
		}
		if sumTime >= 60 {
			state = 2
		}
	}
	if state == 0 {
		return errors.New("还未到奖励时间")
	}
	var t tables.StatisticsShortVideo
	get, err := orm.Db.Where("from_id=? and user_id=?", req.VideoId, user.Id).Get(&t)
	if err != nil {
		return err
	}
	if get {
		id = t.Id
		if t.Type == 2 {
			return errors.New("以奖励完")
		}

	}
	// 如果是免费视频则加10 付费视频则加20 积分
	info, err := s.Info(req.VideoId, "total_amount,id")
	if err != nil {
		return err
	}

	// 30秒收费 30 免费20 60秒收费40 免费30
	if state == 1 {
		if info.TotalAmount > 0 {
			points = 30
		} else {
			points = 20
		}
	} else {
		if info.TotalAmount > 0 {
			points = 40
		} else {
			points = 30
		}
	}

	err = User.ScoreV2(user.Id, gconv.Int(points), "观看短视频赠送积分")
	if err != nil {
		return err
	}
	t = tables.StatisticsShortVideo{
		Duration:      float32(req.Duration),
		FromId:        req.VideoId,
		UserId:        user.Id,
		TotalDuration: float32(req.TotalDuration),
		Type:          state,
	}
	if id > 0 {
		orm.Db.Where("id=?", id).Update(t)
	} else {
		orm.Db.Insert(t)
	}
	return nil
}
func (s *shortvideoService) List(c *gin.Context, req *model.ShortVideoReq) (*[]model.ShortRsp,
	int, error) {
	user, err := Request.User(c)
	if err != nil {
		return nil, 0, err
	}
	userId := user.Id
	if req.UserId != 0 {
		userId = req.UserId
	}
	var m tables.Shortvideo
	if req.UserId == 0 && req.Id != 0 {
		get, err := orm.Db.Where("type=? and id=?", 2, req.Id).Get(&m)
		if !get {
			return nil, 0, errors.New("该视频不存在")
		}
		if err != nil {
			return nil, 0, err
		}
		userId = m.UserId
	}
	var m1 []model.ShortRsp
	var count int
	order := fmt.Sprintf("FIELD(id,%d) desc,id desc", req.Id)
	err = dao.Shortvideo.Ctx(c).Where("type=? and user_id=?", 2, userId).Order(order).
		Page(req.PageNo, req.PageSize).ScanAndCount(&m1, &count, true)
	if err != nil {
		return nil, 0, err
	}
	key := []byte("Q!fqhthlsFuazZ(gvlWTY(h(n_x*2i4+")
	iv := []byte("Js8K1kDYC^K^FuWZ")
	for k, item := range m1 {
		if len(item.Video) > 0 && item.Video[0].Url != "" {
			item.Video[0].Url, _ = utils.Common.AESEncrypt([]byte(item.Video[0].Url), key, iv)
			item.VideoStr = item.Video[0].Url
		}
		if item.BindType == 1 {
			var m3 model.ShortVideoGoods
			_ = dao.Goods.Ctx(c).Where("id=?", item.BindId).
				Fields("id,title.price,share_img").
				Scan(&m)
			item.Goods = &m3
			if m3.Id == 0 {
				item.Goods = nil
			}

		} else {
			var m4 model.CouponImg
			err = dao.Coupon.Ctx(c).Where("id=?", item.BindId).
				Fields("id,title,price,share_img").
				Scan(&m4)
			if m4.Id != 0 {
				var ShareImg string
				if len(m4.ShareImg) != 0 {
					ShareImg = gconv.String(m4.ShareImg[0]["url"])
				}
				item.Goods = &model.ShortVideoGoods{
					Id:       m4.Id,
					Title:    m4.Title,
					Price:    m4.Price,
					ShareImg: ShareImg,
				}
			} else {
				item.Goods = nil
			}
		}
		if user.Id > 0 {
			var count1 int64
			count1, err = orm.Db.Table("share_user").
				Where("from_id=? and user_id=? and state=? and share_type=?", item.Id, user.Id, 1, 1).
				Count()
			if count1 > 0 {
				item.IsDz = 1
			}
			count1, err = orm.Db.Table("share_user").
				Where("from_id=? and user_id=? and state=? and share_type=?", item.Id, user.Id, 1, 2).
				Count()
			if count1 > 0 {
				item.IsZf = 1
			}
			var shorOrder tables.ShortOrder
			_ = dao.ShortOrder.Ctx(c).Where("short_video_id=? and user_id =? and state = ?", item.Id,
				user.Id, 1).Scan(&shorOrder)
			if shorOrder.Id > 0 {
				item.IsBuy = 1
				item.IsFeel = 0
			}
		}
		m1[k] = item
	}
	if len(m1) > 1 && req.Id != 0 && req.UserId == 0 {
		for _, rsp := range m1 {
			//第一个键和第二个交换位置
			if rsp.Id == req.Id {
				m1[0], m1[1] = m1[1], m1[0]
				break
			}
		}
	}
	return &m1, count, err
}

func (s *shortvideoService) Save(c *gin.Context, req *model.ShortReq) error {
	user, err := User.Info(c, "sub_mch_id,id,acid")
	if err != nil {
		return err
	}
	data := req.ShortVideo
	if len(req.Video) > 0 && data.Id > 0 {
		key := []byte("Q!fqhthlsFuazZ(gvlWTY(h(n_x*2i4+")
		iv := []byte("Js8K1kDYC^K^FuWZ")
		for k, item := range req.Video {
			decrypt, err := utils.Common.AESDecrypt(item.Url, key, iv)
			if decrypt != "" && err == nil {
				req.Video[k].Url = decrypt
			}
		}
	}
	data.Pic = gjson.StructOrMap2Json(req.Pic)
	data.Video = gjson.StructOrMap2Json(req.Video)
	data.UserId = user.Id
	data.SubMchId = user.SubMchId
	data.BindId = gconv.Int(data.BindId)
	if req.Type == 0 {
		data.Type = 2
	}
	if req.Id > 0 {
		dao.Shortvideo.Ctx(c).Save(data)
	} else {
		_, err = orm.Db.Table("shortvideo").Insert(data)
	}

	return err
}
func (s *shortvideoService) Del(c *gin.Context, req *model.ReqId) error {
	_, err := orm.Db.ID(req.Id).Delete(&tables.Shortvideo{})
	return err
}
